package com.csu.cphone.service.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import com.csu.common.exception.WebException;
import com.csu.common.sms.SMSSender;
import com.csu.common.utils.JsonUtil;
import com.csu.common.utils.RedisUtil;
import com.csu.common.utils.UUIDUtil;
import com.csu.cphone.constants.ErrorCode;
import com.csu.cphone.constants.RedisKey;
import com.csu.cphone.dao.ProducerMapper;
import com.csu.cphone.dao.RecycleOrderMapper;
import com.csu.cphone.dao.RecycleProblemSelectMapper;
import com.csu.cphone.dao.RecycleSelectAnswerMapper;
import com.csu.cphone.pojo.ProducerPojo;
import com.csu.cphone.pojo.RecycleOrderPojo;
import com.csu.cphone.pojo.RecycleProblemPojo;
import com.csu.cphone.pojo.RecycleProblemSelectPojo;
import com.csu.cphone.pojo.RecycleSelectAnswerPojo;
import com.csu.cphone.pojo.StorePojo;
import com.csu.cphone.service.RecycleOrderService;
import com.csu.cphone.service.RecycleService;
import com.csu.cphone.service.StoreService;
import com.csu.cphone.vo.OrderCacheInfo;
import com.csu.cphone.vo.RecycleOrderVo;
import com.csu.cphone.vo.RecyclePhoneProblemsVo;
import com.csu.cphone.vo.RecycleSelectAnswerVo;

/**
 * @项目名称：cphone
 * @类名称：OrderServiceImpl
 * @类描述：订单业务实现类
 * @创建人：阳凯
 * @创建时间：2017年9月20日 下午9:45:41
 */
@Service
public class RecycleOrderServiceImpl implements RecycleOrderService
{

    @Autowired
    private RecycleService recycleService;

    @Autowired
    private StoreService storeService;

    @Autowired
    private RecycleOrderMapper recycleOrderMapper;

    @Autowired
    private RecycleSelectAnswerMapper recycleSelectAnswerMapper;

    @Autowired
    private RecycleProblemSelectMapper recycleProblemSelectMapper;

    @Autowired
    private ProducerMapper producerMapper;

    @Override
    public RecycleOrderPojo commitOrder(RecycleOrderVo orderVo) throws WebException
    {
        String position = orderVo.getPositon();
        checkPosition(position);

        RecyclePhoneProblemsVo recyclePhoneProblems = orderVo.getRecyclePhoneProblems();
        Double amount = recycleService.offer(recyclePhoneProblems);

        RecycleOrderPojo orderPojo = new RecycleOrderPojo();
        orderPojo.setApplyTime(new Date());

        Integer customerId = orderVo.getCustomerId();
        orderPojo.setCustomerId(customerId);
        Integer serviceType = orderVo.getServiceType();
        orderPojo.setServiceType(serviceType);
        orderPojo.setAmount(amount);

        orderPojo.setRemark(orderVo.getRemark());
        String sn = UUIDUtil.getUUID();
        orderPojo.setSerialNumber(sn);
        Integer recyclePhoneId = orderVo.getRecyclePhoneId();
        orderPojo.setRecyclePhoneId(recyclePhoneId);

        List<RecycleProblemSelectPojo> selects = getSelectAnswerPojos(orderVo);

        if (serviceType == 1)
        {
            orderPojo.setStatus(0);
            orderPojo.setAddress(orderVo.getAddress());
            orderPojo.setPeriod(orderVo.getPeriod());
            OrderCacheInfo map = new OrderCacheInfo();
            map.setSn(sn);
            map.setPosition(position);
            RedisUtil.getRedisDb().lpush(RedisKey.WAITING_ORDER_QUEUE + "recycle", JsonUtil.toJSONString(map));
        }
        else if (serviceType == 2)
        {
            orderPojo.setStatus(1);
            Integer storeId = orderVo.getStoreId();
            orderPojo.setStoreId(storeId);
            StorePojo store = storeService.queryById(storeId);
            Integer producerId = store.getProducerId();
            orderPojo.setProducerId(producerId);
            ProducerPojo producer = producerMapper.selectById(producerId);
            String number = producer.getNumber();
            RedisUtil.getRedisDb().lpush(RedisKey.WAITING_RECYCLE_ORDER + number, sn);
        }
        else if (serviceType == 3)
        {
            orderPojo.setStatus(2);
            orderPojo.setProducerId(-1);
            orderPojo.setExpressCompany(orderVo.getExpressCompany());
            orderPojo.setExpressNumber(orderVo.getExpressNumber());
            orderPojo.setIphonePasswd(orderVo.getIphonePasswd());
        }
        else
        {
            throw new WebException(ErrorCode.SERVICE_TYPE_ERROR_CODE, ErrorCode.SERVICE_TYPE_ERROR_MEASSAGE);
        }
        insert(sn, recyclePhoneId, selects, orderPojo);
        RedisUtil.getRedisDb().hset(RedisKey.ORDER_POSITION, sn, position);
        return orderPojo;
    }

    /**
     * @description
     * @author TangC
     * @date 2017年12月16日 上午10:47:32
     * @param position
     * @throws WebException
     */
    private void checkPosition(String position) throws WebException
    {
        String[] positions = position.split(",");
        String latString = positions[0];
        String lngString = positions[1];
        if (StringUtils.isEmpty(lngString) || StringUtils.isEmpty(latString))
        {
            throw new WebException(ErrorCode.OrderPositionError, ErrorCode.OrderPositionMessgae);
        }
    }

    @Override
    public RecycleOrderPojo updateOrder(RecycleOrderPojo orderPojo)
    {

        List<RecycleProblemSelectPojo> selects = orderPojo.getProblemSelects();
        Double amount = recycleService.offerBySelects(selects, orderPojo.getRecyclePhoneId());
        orderPojo.setAmount(amount);
        orderPojo.setAcceptTime(new Date());
        orderPojo.setStatus(2);
        update(orderPojo.getSerialNumber(), orderPojo.getRecyclePhoneId(), selects, orderPojo);

        return orderPojo;
    }

    @Override
    public List<RecycleOrderPojo> queryOrdersByCustomerId(Integer customerId)
    {
        List<RecycleOrderPojo> recycleOrders = recycleOrderMapper.selectByCustomerId(customerId);

        if (recycleOrders != null)
        {
            for (RecycleOrderPojo recycleOrder : recycleOrders)
            {
                List<RecycleProblemSelectPojo> problemSelects = getProblemSelects(recycleOrder.getSerialNumber());
                recycleOrder.setProblemSelects(problemSelects);
                List<RecycleProblemPojo> problems = recycleService.getRecycleProblems(recycleOrder.getRecyclePhoneId());
                recycleOrder.setProblems(problems);
            }
        }
        return recycleOrders;
    }

    /**
     * @see com.csu.cphone.service.RecycleOrderService#getOrderBySn(java.lang.String)
     */
    @Override
    public RecycleOrderPojo getOrderBySn(String serialNumber)
    {
        RecycleOrderPojo recycleOrder = recycleOrderMapper.selectBySn(serialNumber);
        List<RecycleProblemSelectPojo> problemSelects = getProblemSelects(recycleOrder.getSerialNumber());
        recycleOrder.setProblemSelects(problemSelects);

        List<RecycleProblemPojo> problems = recycleService.getRecycleProblems(recycleOrder.getRecyclePhoneId());
        recycleOrder.setProblems(problems);
        return recycleOrder;
    }

    /**
     * @description
     * @author TangC
     * @date 2017年11月9日 下午10:28:59
     * @param sn
     * @param recyclePhoneId
     * @param selects
     * @param orderPojo
     */
    @Transactional
    private void update(String sn, Integer recyclePhoneId, List<RecycleProblemSelectPojo> selects,
            RecycleOrderPojo orderPojo)
    {
        updateAnswer(selects, sn, recyclePhoneId);
        recycleOrderMapper.update(orderPojo);
    }

    /**
     * @description
     * @author TangC
     * @date 2017年11月9日 下午10:32:45
     * @param selects
     * @param sn
     * @param recyclePhoneId
     */

    private int updateAnswer(List<RecycleProblemSelectPojo> selects, String sn, Integer recyclePhoneId)
    {
        List<RecycleSelectAnswerPojo> newAnswerPojos = new ArrayList<RecycleSelectAnswerPojo>();
        Map<Integer, RecycleSelectAnswerPojo> newAnswerMap = new HashMap<Integer, RecycleSelectAnswerPojo>();
        Map<Integer, RecycleSelectAnswerPojo> oldAnswerMap = new HashMap<Integer, RecycleSelectAnswerPojo>();
        for (RecycleProblemSelectPojo select : selects)
        {
            RecycleSelectAnswerPojo answerPojo = new RecycleSelectAnswerPojo();
            answerPojo.setRecycleOrderSn(sn);
            answerPojo.setRecyclePhoneId(recyclePhoneId);
            answerPojo.setRecycleProblemId(select.getProblemId());
            Integer selectId1 = select.getId();
            answerPojo.setRecycleProblemSelectId(selectId1);
            answerPojo.setCost(select.getCost());
            newAnswerPojos.add(answerPojo);

            newAnswerMap.put(selectId1, answerPojo);
        }

        List<RecycleSelectAnswerPojo> oldAnswerPojos = recycleSelectAnswerMapper.selectByOrderSn(sn);

        List<Integer> delIds = new ArrayList<Integer>();
        List<RecycleSelectAnswerPojo> addAnswers = new ArrayList<RecycleSelectAnswerPojo>();
        Set<Integer> modifyIds = new HashSet<Integer>();
        for (RecycleSelectAnswerPojo oldAnswerPojo : oldAnswerPojos)
        {
            Integer selectId2 = oldAnswerPojo.getRecycleProblemSelectId();
            oldAnswerMap.put(selectId2, oldAnswerPojo);

            if (newAnswerMap.containsKey(selectId2))
            {
                continue;
            }
            Integer delId = oldAnswerPojo.getId();
            delIds.add(delId);
            modifyIds.add(selectId2);
        }

        for (RecycleSelectAnswerPojo newAnswerPojo : newAnswerPojos)
        {
            Integer selectId3 = newAnswerPojo.getRecycleProblemSelectId();
            if (oldAnswerMap.containsKey(selectId3))
            {
                continue;
            }
            addAnswers.add(newAnswerPojo);
            modifyIds.add(selectId3);
        }

        if (!CollectionUtils.isEmpty(delIds))
        {
            recycleSelectAnswerMapper.batchDel(delIds);
        }
        if (!CollectionUtils.isEmpty(addAnswers))
        {
            recycleSelectAnswerMapper.batchInsert(addAnswers);
        }

        return modifyIds.size();

    }

    /**
     * @description
     * @author TangC
     * @date 2017年11月4日 下午12:01:31
     * @param sn
     * @param recyclePhoneId
     * @param selects
     */
    @Transactional
    private void insert(String sn, Integer recyclePhoneId, List<RecycleProblemSelectPojo> selects,
            RecycleOrderPojo orderPojo)
    {
        if (!CollectionUtils.isEmpty(selects))
        {
            insertAnswer(selects, sn, recyclePhoneId);
        }
        recycleOrderMapper.insert(orderPojo);
    }

    private int insertAnswer(List<RecycleProblemSelectPojo> selects, String sn, Integer recyclePhoneId)
    {
        List<RecycleSelectAnswerPojo> answerPojos = new ArrayList<RecycleSelectAnswerPojo>();

        for (RecycleProblemSelectPojo select : selects)
        {
            RecycleSelectAnswerPojo answerPojo = new RecycleSelectAnswerPojo();
            answerPojo.setRecycleOrderSn(sn);
            answerPojo.setRecyclePhoneId(recyclePhoneId);
            answerPojo.setRecycleProblemId(select.getProblemId());
            answerPojo.setRecycleProblemSelectId(select.getId());
            answerPojo.setCost(select.getCost());
            answerPojos.add(answerPojo);
        }

        return recycleSelectAnswerMapper.batchInsert(answerPojos);
    }

    /**
     * @description
     * @author TangC
     * @date 2017年11月4日 上午11:57:58
     * @param orderVo
     * @return
     */

    private List<RecycleProblemSelectPojo> getSelectAnswerPojos(RecycleOrderVo orderVo)
    {

        RecyclePhoneProblemsVo recyclePhoneProblems = orderVo.getRecyclePhoneProblems();
        List<RecycleSelectAnswerVo> answerVos = recyclePhoneProblems.getAnswers();

        List<Integer> selectIds = new ArrayList<Integer>();
        for (RecycleSelectAnswerVo answerVo : answerVos)
        {
            List<Integer> selectIdList = answerVo.getSelectIds();
            selectIds.addAll(selectIdList);
        }
        List<RecycleProblemSelectPojo> selects = recycleProblemSelectMapper.selectBySelectIds(selectIds);
        return selects;
    }

    /**
     * @see com.csu.cphone.service.RecycleOrderService#queryById(java.lang.Integer)
     */
    @Override
    public RecycleOrderPojo queryById(Integer recycleOrderId)
    {

        RecycleOrderPojo recycleOrder = recycleOrderMapper.selectById(recycleOrderId);
        List<RecycleProblemSelectPojo> problemSelects = getProblemSelects(recycleOrder.getSerialNumber());
        recycleOrder.setProblemSelects(problemSelects);
        List<RecycleProblemPojo> problems = recycleService.getRecycleProblems(recycleOrder.getRecyclePhoneId());
        recycleOrder.setProblems(problems);
        return recycleOrder;
    }

    /**
     * @see com.csu.cphone.service.RecycleOrderService#count()
     */
    @Override
    public Integer count()
    {
        return recycleOrderMapper.count();
    }

    /**
     * @see com.csu.cphone.service.RecycleOrderService#queryList(java.lang.Integer,
     *      java.lang.Integer, java.lang.String)
     */
    @Override
    public List<RecycleOrderPojo> queryList(Integer pageSize, Integer startIndex, String order)
    {
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("pageSize", pageSize);
        map.put("startIndex", startIndex);
        map.put("order", order);

        List<RecycleOrderPojo> recycleOrders = recycleOrderMapper.queryList(map);

        if (recycleOrders != null)
        {
            for (RecycleOrderPojo recycleOrder : recycleOrders)
            {
                List<RecycleProblemSelectPojo> problemSelects = getProblemSelects(recycleOrder.getSerialNumber());
                recycleOrder.setProblemSelects(problemSelects);
                List<RecycleProblemPojo> problems = recycleService.getRecycleProblems(recycleOrder.getRecyclePhoneId());
                recycleOrder.setProblems(problems);
            }
        }
        return recycleOrders;
    }

    /**
     * @see com.csu.cphone.service.RecycleOrderService#deleteById(java.lang.Integer)
     */
    @Override
    public Integer deleteById(Integer recycleOrderId)
    {
        return recycleOrderMapper.deleteById(recycleOrderId);
    }

    /**
     * @see com.csu.cphone.service.RecycleOrderService#cancelOrder(int, int)
     */
    @Override
    public Integer cancelOrder(String orderSn, int customerId)
    {
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("customerId", customerId);
        map.put("cancelTime", new Date());
        map.put("serialNumber", orderSn);
        return recycleOrderMapper.cancelOrder(map);
    }

    /**
     * @see com.csu.cphone.service.RecycleOrderService#getWaitingOrder(int)
     */
    @Override
    public List<RecycleOrderPojo> getWaitingOrder(String number)
    {
        RedisUtil.getRedisDb().del(RedisKey.WAITING_RECYCLE_ORDER + number);
        ProducerPojo producer = producerMapper.selectByNumber(number);
        Integer producerId = producer.getId();
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("producerId", producerId);
        map.put("status", 1);
        List<RecycleOrderPojo> recycleOrders = recycleOrderMapper.getByProducerIdAndStatus(map);
        if (recycleOrders != null)
        {
            for (RecycleOrderPojo recycleOrder : recycleOrders)
            {
                List<RecycleProblemSelectPojo> problemSelects = getProblemSelects(recycleOrder.getSerialNumber());
                recycleOrder.setProblemSelects(problemSelects);
                List<RecycleProblemPojo> problems = recycleService.getRecycleProblems(recycleOrder.getRecyclePhoneId());
                recycleOrder.setProblems(problems);
            }
        }
        return recycleOrders;
    }

    /**
     * @description
     * @author TangC
     * @date 2017年12月16日 下午10:00:11
     * @param serialNumber
     * @return
     */
    private List<RecycleProblemSelectPojo> getProblemSelects(String serialNumber)
    {
        List<RecycleSelectAnswerPojo> recycleSelectAnswers = recycleSelectAnswerMapper.selectByOrderSn(serialNumber);
        List<Integer> selectIds = new ArrayList<Integer>();
        List<RecycleProblemSelectPojo> problemSelects = new ArrayList<RecycleProblemSelectPojo>();
        if (!CollectionUtils.isEmpty(recycleSelectAnswers))
        {
            for (RecycleSelectAnswerPojo recycleSelectAnswer : recycleSelectAnswers)
            {
                Integer selectId = recycleSelectAnswer.getRecycleProblemSelectId();
                selectIds.add(selectId);
            }
            problemSelects = recycleProblemSelectMapper.selectByIds(selectIds);
        }
        return problemSelects;
    }

    /**
     * @see com.csu.cphone.service.RecycleOrderService#finishOrder(java.lang.String)
     */
    @Override
    public Integer finishOrder(String serialNumber)
    {
        RecycleOrderPojo orderPojo = new RecycleOrderPojo();
        orderPojo.setFinishTime(new Date());
        orderPojo.setStatus(3);
        orderPojo.setSerialNumber(serialNumber);
        Integer update = recycleOrderMapper.update(orderPojo);

        if (update != null && update != 0)
        {
            String number = recycleOrderMapper.selectNumberBySn(serialNumber);
            if (number != null)
            {
                SMSSender.sendSMSByType(number, null, 4);
            }
        }

        return update;
    }

    /**
     * @see com.csu.cphone.service.RecycleOrderService#confirmFinish(java.lang.String)
     */
    @Override
    public Integer confirmFinish(String serialNumber)
    {
        RecycleOrderPojo orderPojo = new RecycleOrderPojo();
        orderPojo.setConfirmTime(new Date());
        orderPojo.setStatus(4);
        orderPojo.setSerialNumber(serialNumber);
        return recycleOrderMapper.update(orderPojo);
    }

    /**
     * @see com.csu.cphone.service.RecycleOrderService#queryOrderByProducer(java.lang.String,
     *      java.lang.Integer)
     */
    @Override
    public List<RecycleOrderPojo> queryOrderByProducer(String number, Integer status)
    {
        if (status == null || status == 1)
        {
            RedisUtil.getRedisDb().del(RedisKey.WAITING_RECYCLE_ORDER + number);
        }
        ProducerPojo producer = producerMapper.selectByNumber(number);
        Integer producerId = producer.getId();
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("producerId", producerId);
        map.put("status", status);
        List<RecycleOrderPojo> recycleOrders = recycleOrderMapper.getByProducerIdAndStatus(map);
        if (recycleOrders != null)
        {
            for (RecycleOrderPojo recycleOrder : recycleOrders)
            {
                List<RecycleProblemSelectPojo> problemSelects = getProblemSelects(recycleOrder.getSerialNumber());
                recycleOrder.setProblemSelects(problemSelects);
                List<RecycleProblemPojo> problems = recycleService.getRecycleProblems(recycleOrder.getRecyclePhoneId());
                recycleOrder.setProblems(problems);
            }
        }
        return recycleOrders;
    }

    /**
     * @see com.csu.cphone.service.RecycleOrderService#turnOrder(java.lang.String,
     *      java.lang.String)
     */
    @Override
    public RecycleOrderPojo turnOrder(String sn, String number) throws WebException
    {
        ProducerPojo producer = producerMapper.selectByNumber(number);
        if (producer == null)
        {
            throw new WebException(ErrorCode.UserNullCode, ErrorCode.UserNullMessgae);
        }
        RecycleOrderPojo order = recycleOrderMapper.selectBySn(sn);
        if (order == null)
        {
            throw new WebException(ErrorCode.OrderNullError, ErrorCode.OrderNullMessgae);
        }

        order.setProducerId(producer.getId());
        order.setAcceptTime(new Date());
        recycleOrderMapper.update(order);
        return order;
    }
}
